﻿using FreeSql.DataAnnotations;
using System.Reflection;
using System.Text;

namespace BBCore.Server.PublicComponentBase
{
    /// <summary>
    /// 单表Crud导入导出代码生成器
    /// </summary>
    public class Single_Table_CodeGenerator
    {
        /// <summary>
        /// 表类型
        /// </summary>
        private readonly Type _entityType;
        /// <summary>
        /// 命名空间
        /// </summary>
        private readonly string _namespace;
        /// <summary>
        /// 输出路径
        /// </summary>
        private readonly string _outputPath;
        /// <summary>
        /// 要排除的基类字段 
        /// </summary>
        private readonly Type _baseTypeToExclude;
        /// <summary>
        /// 排除主键和自增字段
        /// </summary>
        private readonly List<string> _propertiesToExclude;
        
        public Single_Table_CodeGenerator(Type entityType, string @namespace, string outputPath, Type baseTypeToExclude)
        {
            _entityType = entityType;
            _namespace = @namespace;
            _outputPath = outputPath;
            _baseTypeToExclude = baseTypeToExclude;
            _propertiesToExclude = GetPropertiesToExclude(entityType);
        }
        /// <summary>
        /// 生成单表Crud导入导出前端和后端代码
        /// </summary>
        public void Single_Table_Generate()
        {
            GenerateRazorPage();
            GenerateService();
        }
        /// <summary>
        /// 排除主键和自增字段
        /// </summary>
        /// <param name="type">TModel</param>
        /// <returns></returns>
        private List<string> GetPropertiesToExclude(Type type)
        {
            var properties = type.GetProperties();
            var excludeList = new List<string>();
            foreach (var property in properties)
            {
                var columnAttribute = property.GetCustomAttribute<ColumnAttribute>();
                if (columnAttribute?.IsPrimary == true || columnAttribute?.IsIdentity == true)
                {
                    excludeList.Add(property.Name);
                }
            }
            return excludeList;
        }
        /// <summary>
        /// razor前端页面
        /// </summary>
        private void GenerateRazorPage()
        {
            var sb = new StringBuilder();
            sb.AppendLine("@page \"/" + _entityType.Name.ToLower() + "s\"");
            sb.AppendLine("@using BBCore.Core.Models.Samples");
            sb.AppendLine("@using BBCore.Application.Interface");
            sb.AppendLine("@using BBCore.Server.PublicComponentBase");
            sb.AppendLine("@using BBCore.Core.Models.EnumTypes");
            sb.AppendLine("@inherits Single_Table_ComponentBase");
            sb.AppendLine("@inject IDataQueryService<" + _entityType.Name + "> IDataQueryService");
            sb.AppendLine("<Table TItem=\"" + _entityType.Name + "\" @ref=\"_table\"");
            sb.AppendLine("       IsBordered=\"true\" IsStriped=\"true\" IsPagination=\"true\" PageItemsSource=\"new int[] { 10, 20,100}\"");
            sb.AppendLine("       ShowEmpty=\"true\" EmptyText=\"暂无数据\" EmptyImage=\"images/empty.svg\"");
            sb.AppendLine("       ShowSkeleton=\"true\" ShowLoading=\"true\" ShowSearch=\"true\"");
            sb.AppendLine("       OnQueryAsync=\"@OnQueryAsync\" OnDeleteAsync=\"@OnDeleteAsync\" OnSaveAsync=\"@OnSaveAsync\"");
            sb.AppendLine("       ShowAddButton=\"@AuthorizeButton(ButtonPermissionTypeEnum.Add)\"");
            sb.AppendLine("       ShowEditButton=\"@AuthorizeButton(ButtonPermissionTypeEnum.Edit)\"");
            sb.AppendLine("       ShowDeleteButton=\"@AuthorizeButton(ButtonPermissionTypeEnum.Del)\"");
            sb.AppendLine("       ShowExtendEditButton=\"@AuthorizeButton(ButtonPermissionTypeEnum.Edit)\"");
            sb.AppendLine("       ShowExtendDeleteButton=\"@AuthorizeButton(ButtonPermissionTypeEnum.Del)\"");
            sb.AppendLine("       ShowToolbar=\"true\" ShowExtendButtons=\"true\"");
            sb.AppendLine("       ShowExportButton=\"true\">");
            sb.AppendLine("    <TableToolbarTemplate>");
            sb.AppendLine("        <TableToolbarButton Color=\"Color.Primary\" Text=\"模板下载\" Icon=\"fas fa-download\" IsShow=\"@AuthorizeButton(ButtonPermissionTypeEnum.Template)\" OnClick=\"tempDownload\"></TableToolbarButton>");
            sb.AppendLine("        @if (AuthorizeButton(ButtonPermissionTypeEnum.Import))");
            sb.AppendLine("        {");
            sb.AppendLine("            <TableToolbarComponent TItem=\"" + _entityType.Name + "\">");
            sb.AppendLine("                <ButtonUpload TValue=\"string\" ShowUploadFileList=\"false\" BrowserButtonClass=\"btn-secondary\"");
            sb.AppendLine("                              Accept=\".xlsx, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\" BrowserButtonText=\"导入\" OnChange=\"DataImport\"></ButtonUpload>");
            sb.AppendLine("            </TableToolbarComponent>");
            sb.AppendLine("        }");
            sb.AppendLine("    </TableToolbarTemplate>");
            sb.AppendLine("    <TableColumns>");
            foreach (var property in _entityType.GetProperties().Where(p => p.DeclaringType != _baseTypeToExclude && !_propertiesToExclude.Contains(p.Name)))
            {
                sb.AppendLine($" <TableColumn @bind-Field=\"@context.{property.Name}\" ></TableColumn>");
            }
            sb.AppendLine("    </TableColumns>");
            sb.AppendLine("</Table>");
            var entityFolder = Path.Combine(_outputPath, "Single_Table_CodeGenerator");
            if (!Directory.Exists(entityFolder))
            {
                Directory.CreateDirectory(entityFolder);
            }
            File.WriteAllText(Path.Combine(entityFolder, _entityType.Name + "_TMP.razor"), sb.ToString());
        }
        /// <summary>
        ///后端代码
        /// </summary>
        private void GenerateService()
        {
            var sb = new StringBuilder();
            sb.AppendLine("using BootstrapBlazor.Components;");
            sb.AppendLine("using BBCore.Core.Models.Samples;");
            sb.AppendLine("using BBCore.Application.Interface;");
            sb.AppendLine();
            sb.AppendLine($"namespace BBCore.Server.Components.Pages.Samples");
            sb.AppendLine("{");
            sb.AppendLine($"    public partial class {_entityType.Name}_TMP");
            sb.AppendLine("    {");
            sb.AppendLine($"        private Table<{_entityType.Name}>? _table;");
            sb.AppendLine($"        private async Task<QueryData<{_entityType.Name}>> OnQueryAsync(QueryPageOptions option) => await IDataQueryService.OnQueryAsync(option);");
            sb.AppendLine($"        private async Task<bool> OnDeleteAsync(IEnumerable<{_entityType.Name}> items)");
            sb.AppendLine("        {");
            sb.AppendLine($"            await freeSql.Delete<{_entityType.Name}>().Where(items).ExecuteAffrowsAsync();");
            sb.AppendLine("            return await Task.FromResult(true);");
            sb.AppendLine("        }");
            sb.AppendLine($"        private async Task<bool> OnSaveAsync({_entityType.Name} item, ItemChangedType changedType)");
            sb.AppendLine("        {");
            sb.AppendLine("            if (changedType == ItemChangedType.Add)");
            sb.AppendLine("            {");
            sb.AppendLine($"                await freeSql.Insert(item).ExecuteAffrowsAsync();");
            sb.AppendLine("            }");
            sb.AppendLine("            else if (changedType == ItemChangedType.Update)");
            sb.AppendLine("            {");
            sb.AppendLine($"                await freeSql.Update<{_entityType.Name}>().SetSource(item).ExecuteAffrowsAsync();");
            sb.AppendLine("            }");
            sb.AppendLine("            return await Task.FromResult(true);");
            sb.AppendLine("        }");
            sb.AppendLine($"        private async Task tempDownload()");
            sb.AppendLine("        {");
            sb.AppendLine($"           var filepath = await IExporterAndImporterService.TemplateDownloadAsync<{_entityType.Name}>();");
            sb.AppendLine("            await DownloadFromFileAsync(filepath);");
            sb.AppendLine("            await ShowToastMessageAsync(\"模板下载\",ToastCategory.Success);");
            sb.AppendLine("        }");
            sb.AppendLine($"        private async Task DataImport(UploadFile uploadFile)");
            sb.AppendLine("        {");
            sb.AppendLine($"            await Data_Import<{_entityType.Name}>(uploadFile);");
            sb.AppendLine("            await _table!.QueryAsync();");
            sb.AppendLine("        }");
            sb.AppendLine("    }");
            sb.AppendLine("}");

            var entityFolder = Path.Combine(_outputPath, "Single_Table_CodeGenerator");
            if (!Directory.Exists(entityFolder))
            {
                Directory.CreateDirectory(entityFolder);
            }
            File.WriteAllText(Path.Combine(entityFolder, _entityType.Name + "_TMP.razor.cs"), sb.ToString());
        }
    }
}
